#include <QtGui>
#include <QTimer>

#include <iostream>
#include <string>

#include "ControlBoard.h"
#include "Debug.h"

/**
 * @brief The constructor of ControlBoard
 *
 * All the widgets used in the GUI part of myfirstplayer are
 * created in the constructor of ControlBoard.
 *
 */
ControlBoard::ControlBoard()
{
	QWidget *widget = new QWidget();

	playState = StateStop;
	prevPath = "";

	createActions();
	createMenus();

	setCentralWidget(widget);

	/* Create title label. */
	title = new QLabel("Title");
	title->setFont(QFont("Times", 10, QFont::Bold));

	/* Create bottons "Play" and "Stop" and connect the signal to
	 * corresponding callback functions. */
	play_b = new QPushButton(tr("&Play"));
	stop_b = new QPushButton(tr("&Stop"));
	play_b->setFont(QFont("Times", 10, QFont::Normal));
	stop_b->setFont(QFont("Times", 10, QFont::Normal));
	play_b->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
	stop_b->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

	connect( play_b, SIGNAL(clicked()), this, SLOT(play_and_pause()) );
	connect( stop_b, SIGNAL(clicked()), this, SLOT(stop()) );

	mySlider = new TimerSlider;
	mySlider->disableSlider();
	connect( mySlider, SIGNAL(sliderPressed()), this, SLOT(sliderPressed()) );
	connect( mySlider, SIGNAL(sliderReleased()), this, SLOT(sliderSeek()) );

	/* Initialize the decoder. */
	decoder = (Decoder *) new Decoder_xine();

	/* Create the timer to update the time slider constantly. */
	updateTimer = new QTimer(this);
	connect( updateTimer, SIGNAL(timeout()), this, SLOT(updateSeek()) );

	/* Arrange the layout. */
	QGridLayout *grid = new QGridLayout;

	grid->addWidget(title, 0, 0, 1, 2);
	grid->addWidget(play_b, 1, 0);
	grid->addWidget(stop_b, 2, 0);
	grid->addWidget(mySlider, 1, 1, 2, 2);

	widget->setLayout(grid);

	/* Fix the size of the window to prevent from being resized by
	 * the mouse. */
	setFixedSize(minimumSize());
}

QString
ControlBoard::getFileName() const
{
	return openFileName;
}

void
ControlBoard::setOpenFileName()
{
	QFileDialog::Options options;
	QString selectedFilter;
	QString filterString;

	std::string filter;

	filter = decoder->file_filter();


	/* Add file filter to filterString. */
	if( !filter.empty() ){
		filterString += tr("Media File");
		filterString += " ( ";
		filterString += QString::fromStdString(filter);
		filterString += " ) ";
		filterString += ";;";
	}

	/* Filter for all files */
	filterString += tr("All");
	filterString += " (*)";

	/* Create a file dialog. */
	QString fileName = QFileDialog::getOpenFileName(this,
				tr("Open File"),
				prevPath,
				filterString,
				&selectedFilter,
				options);
	/* Open the selected file. */
	if( !fileName.isEmpty() ){
		int i, length;
		QChar c;
		string stdName;

		openFileName = fileName;
		/* Use toLocal8Bit() for the local encoding compatibility. */
		/* (Using toStdString() on a path containing local encoding
		 * characters leads to a wrong file path.) */
		stdName = fileName.toLocal8Bit().data();
		decoder->open( stdName );

		/* Extract the path from the openFileName. */
		prevPath = openFileName;
		length = openFileName.length();
		for( i = length - 1; i >= 0; i-- ){
			c = openFileName.at( i );
			if( c == '/' )
				break;
		}
		prevPath.truncate( i );

		/* If the previous media is played, stop it. */
		if( playState != StateStop )
			stop();
		/* Start to play */
		play_and_pause();
	}
}

void
ControlBoard::about()
{
	QMessageBox::about(this, tr("About Application"),
			tr("It's nothing but an <b>ABOUT</b>!"));
}

void
ControlBoard::play_and_pause()
{
	switch( playState ){
		case StatePlay:
			/*--- Pause the playback. ---*/
			decoder->pause();

			playState = StatePause;
			play_b->setText(tr("Play"));
			updateTimer->stop();
			break;
		case StatePause:
			/*--- Resume from pause. ---*/
			decoder->resume();

			playState = StatePlay;
			play_b->setText(tr("Pause"));
			updateTimer->start(200);
			break;
		case StateStop:
			/*--- Start to play the media file ---*/

			if( openFileName.isEmpty() )
				break;

			int max;
			/* Play the media file. */
			if( decoder->play(0) < 0 )
				break;
			/* Get the time length of the media file */
			max = decoder->getMediaLength();
			/* Setting the max value of the seek slider */
			mySlider->setMax(max/1000);
			/* Show the title of the media file */
			//! @todo Adjust the length of the MediaInfo String.
			title->setText(QString::fromStdString(
						decoder->getMediaInfo()));

			playState = StatePlay;
			play_b->setText(tr("Pause"));
			updateTimer->start(200);
			break;
		default:
			break;
	}
}

void
ControlBoard::stop()
{
	updateTimer->stop();

	if( playState != StateStop ){
		/* Stop the playback. */
		decoder->stop();

		/* Disable the seek slider. */
		mySlider->disableSlider();
		playState = StateStop;
	}
	play_b->setText(tr("Play"));
	title->setText(tr("Title"));
}

void
ControlBoard::sliderPressed()
{
	if( updateTimer->isActive() )
		updateTimer->stop();
}

void
ControlBoard::sliderSeek()
{
	int pos = mySlider->getValue();
	/* Play the media file at the assigned position. */
	/* Seek Slider: 1 tick = 1 second                */
	decoder->play(1000*pos);

	/* Update playState. */
	play_b->setText(tr("Pause"));
	if( playState == StatePause )
		playState = StatePlay;

	if( !updateTimer->isActive() )
		updateTimer->start(200);
}

void
ControlBoard::updateSeek()
{
	int msec;

	/* If the status of the decoder is STOP, no update is needed. */
	if(decoder->getStatus() == DECODER_STOP){
		stop();
		return;
	}

	/* Get the current position of the playback and update */
	/* the timer and the seek slider.                      */
	msec = decoder->getCurrentPos();
	mySlider->setTimer( msec/1000 );
}

void
ControlBoard::createActions()
{
	openAct = new QAction(tr("&Open"), this);
	connect( openAct, SIGNAL(triggered()), this, SLOT(setOpenFileName()) );
	quitAct = new QAction(tr("&Quit"), this);
	connect( quitAct, SIGNAL(triggered()), this, SLOT(close()) );

	aboutAct = new QAction(tr("About"), this);
	connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void
ControlBoard::createMenus()
{
	fileMenu = menuBar()->addMenu(tr("&File"));
	fileMenu->addAction(openAct);
	fileMenu->addAction(quitAct);

	aboutMenu = menuBar()->addMenu(tr("&Help"));
	aboutMenu->addAction(aboutAct);
}

